package com.bit.cfdi.web.dao.impl;

import java.util.ArrayList;
import java.util.List;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import com.bit.cfdi.web.dao.ImpuestoDAO;
import com.bit.cfdi.web.domain.Giro;
import com.bit.cfdi.web.domain.Impuesto;
import com.bit.cfdi.web.domain.Negocio;

@Repository
public class ImpuestoDAOImpl extends HibernateDaoSupport implements ImpuestoDAO {


	@Autowired
	public void init(final SessionFactory sessionFactory) throws DataAccessException {
		setSessionFactory(sessionFactory);
	}
	
	@SuppressWarnings("unchecked")
	@Override	
	@Transactional public List<Impuesto> getAll() throws DataAccessException {
		return getHibernateTemplate().find(" from Impuesto");
	}

	@Override	
	@Transactional public void save(Impuesto impuesto) throws DataAccessException {
		getHibernateTemplate().saveOrUpdate(impuesto);		
	}

	@SuppressWarnings("unchecked")
	@Override 
	@Transactional public Impuesto getBySiglaTasa(String sigla, 
			double tasa) throws DataAccessException {
		String query = "from Impuesto as p where p.siglaImpuesto = ? and p.tasa = ? ";
		List<Impuesto> impuesto = getHibernateTemplate().find(query, sigla, tasa);
		return impuesto != null && !impuesto.isEmpty() ? impuesto.get(0) : null;
	}

	@SuppressWarnings("unchecked")
	@Override
	/** Realiza la b\u00FAsqueda por la descripcion del giro, si se requiere modificar, favor de implementar findByCriteria()*/
	@Transactional public List<Impuesto> getImpuestoByGiro(
			Giro giro) throws DataAccessException {
		if(giro.getDescripcion() == null) {
			return new ArrayList<Impuesto>(0);
		}
		List<Impuesto> impuestoList = getHibernateTemplate().find("" +
				"SELECT ig.impuesto FROM GiroImpuesto ig WHERE ig.giro.descripcion=?", 
				giro.getDescripcion());

		return impuestoList;
	}

	@SuppressWarnings("unchecked")
	@Override
	/** Realiza la b\u00FAsqueda por el id del negocio, si se requiere modificar, favor de implementar findByCriteria()*/
	@Transactional  public List<Impuesto> getImpuestoByNegocio(
			Negocio negocio) throws DataAccessException {
		List<Impuesto> impuestoList = getHibernateTemplate().find("" +
				"SELECT ineg.impuesto FROM ImpuestoNegocio ineg WHERE " +
				"ineg.negocio.idNegocio=?", negocio.getIdNegocio());
		return impuestoList;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional public List<Impuesto> getImpuestosCategoria(
			String categoria, String tipoImpuesto) throws DataAccessException {
		String query = 
				"from Impuesto as impuesto where impuesto.tipoImpuesto = ? " +
				"and impuesto.tipoImpuesto.categoriaImpuesto = ? ";
		List<Impuesto> listaImpuestos = getHibernateTemplate().find(query, 
				tipoImpuesto, categoria);
		return listaImpuestos;	
	}
	
	@SuppressWarnings("unchecked")
	@Override
	@Transactional public Impuesto getImpuestoCatalogo(
			String categoria, String tipoImpuesto, String nombreImpuesto, 
			String siglaImpuesto) throws DataAccessException {		
		String query = 
				"from Impuesto as impuesto " +
				"where impuesto.tipoImpuesto = ? " +
				"  and impuesto.tipoImpuesto.categoriaImpuesto = ? " +
				"  and impuesto.nombreImpuesto = ? " +
				"  and impuesto.siglaImpuesto = ? ";
		List<Impuesto> listaImpuestos = getHibernateTemplate().find(query, 
				tipoImpuesto, categoria, nombreImpuesto, siglaImpuesto);
		
		return listaImpuestos != null && !listaImpuestos.isEmpty() ? 
				listaImpuestos.get(0) : null;	
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional public Impuesto getImpuestobyGiro(String nombre, String sigla, 
			Giro giro) throws DataAccessException {
		
		String giroDescripcion = "";
		
		if (giro != null)
			giroDescripcion = "x";
		
		List<Impuesto> impuestoList = getHibernateTemplate().find(
				"SELECT impuestoNegocio.impuesto " +
				"FROM ImpuestoGiro as impuestoNegocio " +
				"WHERE impuestoNegocio.giro.descripcion=? " +
				"AND (impuestoNegocio.impuesto.nombreImpuesto = ? " +
				"OR impuestoNegocio.impuesto.siglaImpuesto = ?)", 
				giroDescripcion, nombre, sigla);

		return impuestoList != null && !impuestoList.isEmpty() ? impuestoList.get(0) : null;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional public Impuesto getImpuestobyNegocio(String nombre, String sigla,
			Negocio negocio) throws DataAccessException {
		
		List<Impuesto> impuestoList = getHibernateTemplate().find(
				"SELECT impuestoNegocio.impuesto " +
				"FROM ImpuestoNegocio as impuestoNegocio " +
				"WHERE impuestoNegocio.negocio.idNegocio=? " +
				"AND (impuestoNegocio.impuesto.nombreImpuesto = ? " +
				"OR impuestoNegocio.impuesto.siglaImpuesto = ?)", 
				negocio.getIdNegocio(), nombre, sigla);

		return impuestoList != null && !impuestoList.isEmpty() ? impuestoList.get(0) : null;
	}

	@SuppressWarnings("unchecked")
	/** Realiza la b\u00FAsqueda por el id del negocio y sus siglas */
	@Transactional public List<Impuesto> getImpuestoByNegSiglas(Negocio negocio,
			String sigla) throws DataAccessException {
		List<Impuesto> impuestoList = getHibernateTemplate().find(
				"SELECT ineg.impuesto FROM ImpuestoNegocio ineg WHERE " +
				"ineg.negocio.idNegocio=? AND ineg.impuesto.siglaImpuesto=?", 
									negocio.getIdNegocio(),sigla);
		return impuestoList;
	}
	

	@SuppressWarnings("unchecked")
	@Override
	/** Realiza la b\u00FAsqueda por el id del negocio o default y sus siglas */
	@Transactional public List<Impuesto> getImpBySiglasNegocioDefault(
			Negocio negocio,String sigla,double tasa,String tipo,
			String categoria) throws DataAccessException {
		if(sigla==null) {
			sigla="";
		}
		List<Impuesto> impuestoList = getHibernateTemplate().find("SELECT imp FROM " +
				"ImpuestoNegocio ineg right join ineg.impuesto as imp  WHERE (ineg.negocio =? OR ineg.negocio = null) "
									+" AND lower(imp.siglaImpuesto)=? "
									+" AND imp.tasa=? " 
									+" AND imp.tipoImpuesto=? "
									+" AND imp.categoriaImpuesto=? ", negocio ,sigla.toLowerCase(),tasa,tipo,categoria);
		return impuestoList;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional public List<Impuesto> getByStatusAndNegocio(Integer status, Negocio negocio) throws DataAccessException {
		List<Impuesto> impuesto = getHibernateTemplate().find("select imp "+
				" from ImpuestoNegocio as impNeg right join impNeg.impuesto as imp "+
				" where imp.status = ? and (impNeg.negocio = null or impNeg.negocio = ?)",status, negocio);
		return impuesto;
	}
	
	@SuppressWarnings("unchecked")
	@Override
	@Transactional public List<Impuesto> getImpuestobyCategoriaNegocio(
			String categoria,Negocio negocio,Integer status) throws DataAccessException	{
		List<Impuesto> impuesto = getHibernateTemplate().find("select imp "+
				" from ImpuestoNegocio as impNeg right join impNeg.impuesto as imp "+
				" where imp.status = ? "
				+" AND (imp.tipoImpuesto.categoriaImpuesto  = ? )"
				+" and (impNeg.negocio = null or impNeg.negocio = ?)",status,categoria, negocio);
		return impuesto;
	}

	@SuppressWarnings("unchecked")
	@Override
	@Transactional public Impuesto getByTipoSiglasTasa(final String tipo, final String siglas, 
			final double tasa) throws DataAccessException {
		List<Impuesto> impuestos = getHibernateTemplate().find(
				" from Impuesto as imp" +
				" where imp.tipoImpuesto=?" +
				" and imp.siglaImpuesto=?" +
				" and imp.tasa=?", tipo, siglas, tasa);
		return impuestos.size()>0?impuestos.get(0):null;
	}
}